# -*- coding: utf-8 -*-
"""
  @Time    : 2023/3/1 10:07
  @Author  : 
  @email   : 
  @File    : docker_manage.py
"""
import docker
from flask import current_app


class DockerEngine(object):
    def __init__(self, base_url):
        self.client = docker.DockerClient(base_url=base_url, version="auto")

    def container_info(self, all=True, filters=None):
        """
        获取容器的信息：容器名称，IP，运行状态，pids，cpu限制，内存限制，保留内存等信息
        :param all: 默认True，获取所有容器
        :param filters: 过滤的条件，默认为None，参考：https://docker-py.readthedocs.io/en/stable/containers.html#
        :return: dict
        """
        container_dict = {}
        try:
            container_list = self.client.containers.list(
                all=all, filters=filters)
        except Exception as e:
            current_app.logger.warning(e)
            container_list = []
        for container in container_list:
            container_name = container.attrs['Name'].replace('/', '')
            try:
                net_key = list(container.attrs['NetworkSettings']['Networks'].keys())[0]
                container_ip = container.attrs['NetworkSettings']['Networks'][net_key]['IPAddress']
            except Exception as e:
                current_app.logger.warning(e)
                container_ip = 'null'
            container_state = container.attrs['State']['Status']
            container_limit_pids = container.attrs['HostConfig']['PidsLimit']
            # 单位：核心
            container_limit_cpu = container.attrs['HostConfig']['NanoCpus'] / 1000000000
            # 单位：MB
            container_limit_mem = container.attrs['HostConfig']['Memory'] / 1024 / 1024
            # 单位：MB
            container_reservations_mem = container.attrs['HostConfig']['MemoryReservation'] / 1024 / 1024
            container_dict[container_name] = {}
            container_dict[container_name]['Ip'] = container_ip
            container_dict[container_name]['State'] = container_state
            container_dict[container_name]['PidsLimit'] = container_limit_pids
            container_dict[container_name]['CpusLimit'] = container_limit_cpu
            container_dict[container_name]['MemoryLimit'] = "%sMB" % container_limit_mem
            container_dict[container_name]['MemoryReservation'] = "%sMB" % container_reservations_mem
        return container_dict

    def container_stats(self, container_name=None, decode=False, stream=False):
        """
        获取容器资源使用情况
        :param container_name: 容器名称
        :param decode: 如果设置为true, stream将被动态解码为字典。仅当stream为True时适用。默认为False。
        :param stream: 如果设置为false，则只返回当前统计数据而不是流。默认为True。
        :return:
        """
        container_obj = self.client.containers.get(container_name)
        return container_obj.stats(decode=decode, stream=stream)

    def network_list(self):
        """
        获取网络列表
        :return: dict
        """
        res_dict = {}
        network_list = self.client.networks.list()
        for network_obj in network_list:
            network_id = network_obj.attrs['Id']
            res_dict.update(self.network_get(network_id=network_id))
        return res_dict

    def network_get(self, network_id):
        """
        通过网络ID，获取网络信息
        :param network_id:
        :return: dict
        """

        network_obj = self.client.networks.get(network_id=network_id)
        return network_obj.attrs['Containers']

    def df_info(self):
        """
        获取docker空间使用信息，倒序输出
        :return: dict
        """
        docker_obj = self.client.df()
        res_data = dict()
        res_data['Images'] = list()
        res_data['Containers'] = list()
        # Images space usage
        for image_item in docker_obj['Images']:
            image_dict = dict()
            if image_item['RepoTags']:
                image_dict['RepoTags'] = image_item['RepoTags'][0]
            else:
                image_dict['RepoTags'] = None
            image_dict['Size'] = image_item.get('Size', 0)
            image_dict['SharedSize'] = image_item.get('SharedSize', 0)
            image_dict['UniqueSize'] = image_item['Size'] - \
                image_item['SharedSize']
            res_data['Images'].append(image_dict)
        res_data['Images'].sort(key=lambda x: x['UniqueSize'], reverse=True)
        # Containers space usage
        for container_item in docker_obj['Containers']:
            container_dict = dict()
            container_dict['Id'] = container_item['Id'][0:12]
            container_dict['Names'] = container_item['Names'][0].replace(
                '/', '')
            net_key = list(
                container_item['NetworkSettings']['Networks'].keys())[0]
            container_dict['IPAddress'] = container_item['NetworkSettings']['Networks'][net_key]['IPAddress']
            container_dict['State'] = container_item['State']
            container_dict['SizeRw'] = container_item.get('SizeRw', 0)
            res_data['Containers'].append(container_dict)
        res_data['Containers'].sort(key=lambda x: x['SizeRw'], reverse=True)
        return res_data


if __name__ == '__main__':
    # docker_client = DockerEngine(base_url="tcp://10.184.6.29:2375")
    docker_client = DockerEngine(base_url="tcp://10.60.31.55:2375")
    # docker_client.network_get(network_id="ee067fce4cc21227644207b3f57d723191caadd6a7f00dc7ea55477068cdff5d")
    # docker_client.network_list()
    # docker_client.container_info(filters={"name": "liuhuan7"})
    # docker_client.container_stats(
    #     '427_lv2sz_order',
    #     decode=False,
    #     stream=False)
    docker_client.df_info()


